home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / src / fl_draw_image.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-07  |  17.6 KB  |  632 lines

  1. //
  2. // "$Id: fl_draw_image.cxx,v 1.5 1999/01/07 19:17:38 mike Exp $"
  3. //
  4. // Image drawing routines for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. // I hope a simple and portable method of drawing color and monochrome
  27. // images.  To keep this simple, only a single storage type is
  28. // supported: 8 bit unsigned data, byte order RGB, and pixels are
  29. // stored packed into rows with the origin at the top-left.  It is
  30. // possible to alter the size of pixels with the "delta" argument, to
  31. // add alpha or other information per pixel.  It is also possible to
  32. // change the origin and direction of the image data by messing with
  33. // the "delta" and "linedelta", making them negative, though this may
  34. // defeat some of the shortcuts in translating the image for X.
  35.  
  36. #ifdef WIN32
  37. #include "fl_draw_image_win32.cxx"
  38. #else
  39.  
  40. // A list of assumptions made about the X display:
  41.  
  42. // bits_per_pixel must be one of 8, 16, 24, 32.
  43.  
  44. // scanline_pad must be a power of 2 and greater or equal to 8.
  45.  
  46. // PsuedoColor visuals must have 8 bits_per_pixel (although the depth
  47. // may be less than 8).  This is the only limitation that affects any
  48. // modern X displays, you can't use 12 or 16 bit colormaps.
  49.  
  50. // The mask bits in TrueColor visuals for each color are
  51. // contiguous and have at least one bit of each color.  This
  52. // is not checked for.
  53.  
  54. // For 24 and 32 bit visuals there must be at least 8 bits of each color.
  55.  
  56. ////////////////////////////////////////////////////////////////
  57.  
  58. #include <FL/Fl.H>
  59. #include <FL/fl_draw.H>
  60. #include <FL/x.H>
  61. #include "Fl_XColor.H"
  62.  
  63. static XImage i;    // template used to pass info to X
  64. static int bytes_per_pixel;
  65. static int scanline_add;
  66. static int scanline_mask;
  67.  
  68. static void (*converter)(const uchar *from, uchar *to, int w, int delta);
  69. static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta);
  70.  
  71. static int dir;        // direction-alternator
  72. static int ri,gi,bi;    // saved error-diffusion value
  73.  
  74. #if USE_COLORMAP
  75. ////////////////////////////////////////////////////////////////
  76. // 8-bit converter with error diffusion
  77.  
  78. // I make a 16x16x16 cube of the closest colors in the fltk colormap
  79. // we could allocate to each of the colors in a 4-bit image.  This is
  80. // then used to find the pixel values and actual colors for error diffusion.
  81. static uchar cube[16*16*16];
  82.  
  83. // calculate sum-of-squares error between 4-bit index and pixel colors:
  84. static int calc_error(int r, int g, int b, int i) {
  85.   int t; int s;
  86.   t = ((r<<4)+8)-fl_xmap[0][i].r; s = t*t;
  87.   t = ((g<<4)+8)-fl_xmap[0][i].g; s += t*t;
  88.   t = ((b<<4)+8)-fl_xmap[0][i].b; s += t*t;
  89.   return s;
  90. }
  91.  
  92. // replace the color stored at a location with a better one:
  93. static void improve(uchar *p, int& e, int r, int g, int b, int i) {
  94.   if (i < FL_GRAY_RAMP || i > 255) return;
  95.   int e1 = calc_error(r,g,b,i);
  96.   if (e1 < e) {*p = i; e = e1;}
  97. }
  98.  
  99. static int filled_color_cube;
  100. static void fill_color_cube() {
  101.   filled_color_cube = 1;
  102.   int i;
  103.   // allocate all the colors in the fltk color cube and gray ramp:
  104.   // allocate widely seperated values first so that the bad ones are
  105.   // distributed evenly through the colormap:
  106.   for (i=0;;) {
  107.     fl_xpixel((Fl_Color)(i+FL_COLOR_CUBE));
  108.     i = (i+109)%(FL_NUM_RED*FL_NUM_GREEN*FL_NUM_BLUE); if (!i) break;
  109.   }
  110.   for (i=0;;) {
  111.     fl_xpixel((Fl_Color)(i+FL_GRAY_RAMP));
  112.     i = (i+7)%FL_NUM_GRAY; if (!i) break;
  113.   }
  114.   // fill in the 16x16x16 cube:
  115.   uchar *p = cube;
  116.   for (int r = 0; r<16; r++) {
  117.     for (int g = 0; g<16; g++) {
  118.       for (int b = 0; b<16; b++, p++) {
  119.     // initial try is value from color cube:
  120.     Fl_Color i = fl_color_cube(r*FL_NUM_RED/16, g*FL_NUM_GREEN/16,
  121.                    b*FL_NUM_BLUE/16);
  122.     int e = calc_error(r,g,b,i);
  123.     *p = uchar(i);
  124.     // try neighbor pixels in the cube to see if they are better:
  125.     improve(p,e,r,g,b,i+FL_NUM_RED*FL_NUM_GREEN);
  126.     improve(p,e,r,g,b,i-FL_NUM_RED*FL_NUM_GREEN);
  127.     improve(p,e,r,g,b,i+FL_NUM_GREEN);
  128.     improve(p,e,r,g,b,i-FL_NUM_GREEN);
  129.     improve(p,e,r,g,b,i+1);
  130.     improve(p,e,r,g,b,i-1);
  131.     // try the gray ramp:
  132.     i = fl_gray_ramp(g*FL_NUM_GRAY/15);
  133.     improve(p,e,r,g,b,i);
  134.     improve(p,e,r,g,b,i+1);
  135.     improve(p,e,r,g,b,i-1);
  136.       }
  137.     }
  138.   }
  139. }
  140.  
  141. static void color8_converter(const uchar *from, uchar *to, int w, int delta) {
  142.   if (!filled_color_cube) fill_color_cube();
  143.   int r=ri, g=gi, b=bi;
  144.   int d, td;
  145.   if (dir) {
  146.     dir = 0;
  147.     from = from+(w-1)*delta;
  148.     to = to+(w-1);
  149.     d = -delta;
  150.     td = -1;
  151.   } else {
  152.     dir = 1;
  153.     d = delta;
  154.     td = 1;
  155.   }
  156.   for (; w--; from += d, to += td) {
  157.     r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
  158.     g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
  159.     b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
  160.     Fl_XColor* x = fl_xmap[0] + cube[((r<<4)&0xf00)+(g&0xf0)+(b>>4)];
  161.     r -= x->r;
  162.     g -= x->g;
  163.     b -= x->b;
  164.     *to = uchar(x->pixel);
  165.   }
  166.   ri = r; gi = g; bi = b;
  167. }
  168.  
  169. static void mono8_converter(const uchar *from, uchar *to, int w, int delta) {
  170.   if (!filled_color_cube) fill_color_cube();
  171.   int r=ri;
  172.   int d, td;
  173.   if (dir) {
  174.     dir = 0;
  175.     from = from+(w-1)*delta;
  176.     to = to+(w-1);
  177.     d = -delta;
  178.     td = -1;
  179.   } else {
  180.     dir = 1;
  181.     d = delta;
  182.     td = 1;
  183.   }
  184.   for (; w--; from += d, to += td) {
  185.     r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
  186.     Fl_XColor* x = fl_xmap[0] + cube[(r>>4)*0x111];
  187.     r -= x->g;
  188.     *to = uchar(x->pixel);
  189.   }
  190.   ri = r;
  191. }
  192.  
  193. #endif
  194.  
  195. ////////////////////////////////////////////////////////////////
  196. // 16 bit TrueColor converters with error diffusion
  197. // Cray computers have no 16-bit type, so we use character pointers
  198. // (which may be slow)
  199.  
  200. #ifdef U16
  201. #define OUTTYPE U16
  202. #define OUTSIZE 1
  203. #define OUTASSIGN(v) *t = v
  204. #else
  205. #define OUTTYPE uchar
  206. #define OUTSIZE 2
  207. #define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt)
  208. #endif
  209.  
  210. static void color16_converter(const uchar *from, uchar *to, int w, int delta) {
  211.   OUTTYPE *t = (OUTTYPE *)to;
  212.   int d, td;
  213.   if (dir) {
  214.     dir = 0;
  215.     from = from+(w-1)*delta;
  216.     t = t+(w-1)*OUTSIZE;
  217.     d = -delta;
  218.     td = -OUTSIZE;
  219.   } else {
  220.     dir = 1;
  221.     d = delta;
  222.     td = OUTSIZE;
  223.   }
  224.   int r=ri, g=gi, b=bi;
  225.   for (; w--; from += d, t += td) {
  226.     r = (r&~fl_redmask)  +from[0]; if (r>255) r = 255;
  227.     g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255;
  228.     b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255;
  229.     OUTASSIGN((
  230.       ((r&fl_redmask)<<fl_redshift)+
  231.       ((g&fl_greenmask)<<fl_greenshift)+
  232.       ((b&fl_bluemask)<<fl_blueshift)
  233.       ) >> fl_extrashift);
  234.   }
  235.   ri = r; gi = g; bi = b;
  236. }
  237.  
  238. static void mono16_converter(const uchar *from,uchar *to,int w, int delta) {
  239.   OUTTYPE *t = (OUTTYPE *)to;
  240.   int d, td;
  241.   if (dir) {
  242.     dir = 0;
  243.     from = from+(w-1)*delta;
  244.     t = t+(w-1)*OUTSIZE;
  245.     d = -delta;
  246.     td = -OUTSIZE;
  247.   } else {
  248.     dir = 1;
  249.     d = delta;
  250.     td = OUTSIZE;
  251.   }
  252.   uchar mask = fl_redmask & fl_greenmask & fl_bluemask;
  253.   int r=ri;
  254.   for (; w--; from += d, t += td) {
  255.     r = (r&~mask) + *from; if (r > 255) r = 255;
  256.     uchar m = r&mask;
  257.     OUTASSIGN((
  258.       (m<<fl_redshift)+
  259.       (m<<fl_greenshift)+
  260.       (m<<fl_blueshift)
  261.       ) >> fl_extrashift);
  262.   }
  263.   ri = r;
  264. }
  265.  
  266. // special-case the 5r6g5b layout used by XFree86:
  267.  
  268. static void c565_converter(const uchar *from, uchar *to, int w, int delta) {
  269.   OUTTYPE *t = (OUTTYPE *)to;
  270.   int d, td;
  271.   if (dir) {
  272.     dir = 0;
  273.     from = from+(w-1)*delta;
  274.     t = t+(w-1)*OUTSIZE;
  275.     d = -delta;
  276.     td = -OUTSIZE;
  277.   } else {
  278.     dir = 1;
  279.     d = delta;
  280.     td = OUTSIZE;
  281.   }
  282.   int r=ri, g=gi, b=bi;
  283.   for (; w--; from += d, t += td) {
  284.     r = (r&7)+from[0]; if (r>255) r = 255;
  285.     g = (g&3)+from[1]; if (g>255) g = 255;
  286.     b = (b&7)+from[2]; if (b>255) b = 255;
  287.     OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3));
  288.   }
  289.   ri = r; gi = g; bi = b;
  290. }
  291.  
  292. static void m565_converter(const uchar *from,uchar *to,int w, int delta) {
  293.   OUTTYPE *t = (OUTTYPE *)to;
  294.   int d, td;
  295.   if (dir) {
  296.     dir = 0;
  297.     from = from+(w-1)*delta;
  298.     t = t+(w-1)*OUTSIZE;
  299.     d = -delta;
  300.     td = -OUTSIZE;
  301.   } else {
  302.     dir = 1;
  303.     d = delta;
  304.     td = OUTSIZE;
  305.   }
  306.   int r=ri;
  307.   for (; w--; from += d, t += td) {
  308.     r = (r&7) + *from; if (r > 255) r = 255;
  309.     OUTASSIGN((r>>3) * 0x841);
  310.   }
  311.   ri = r;
  312. }
  313.  
  314. ////////////////////////////////////////////////////////////////
  315. // 24bit TrueColor converters:
  316.  
  317. static void rgb_converter(const uchar *from, uchar *to, int w, int delta) {
  318.   int d = delta-3;
  319.   for (; w--; from += d) {
  320.     *to++ = *from++;
  321.     *to++ = *from++;
  322.     *to++ = *from++;
  323.   }
  324. }
  325.  
  326. static void bgr_converter(const uchar *from, uchar *to, int w, int delta) {
  327.   for (; w--; from += delta) {
  328.     uchar r = from[0];
  329.     uchar g = from[1];
  330.     *to++ = from[2];
  331.     *to++ = g;
  332.     *to++ = r;
  333.   }
  334. }
  335.  
  336. static void rrr_converter(const uchar *from, uchar *to, int w, int delta) {
  337.   for (; w--; from += delta) {
  338.     *to++ = *from;
  339.     *to++ = *from;
  340.     *to++ = *from;
  341.   }
  342. }
  343.  
  344. ////////////////////////////////////////////////////////////////
  345. // 32bit TrueColor converters on a 32 or 64-bit machine:
  346.  
  347. #ifdef U64
  348. #define STORETYPE U64
  349. #if WORDS_BIGENDIAN
  350. #define INNARDS32(f) \
  351.   U64 *t = (U64*)to; \
  352.   int w1 = (w+1)/2; \
  353.   for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);}
  354. #else
  355. #define INNARDS32(f) \
  356.   U64 *t = (U64*)to; \
  357.   int w1 = (w+1)/2; \
  358.   for (; w1--; from += delta) {U64 i=f; from+= delta; *t++ = ((U64)(f)<<32)|i;}
  359. #endif
  360. #else
  361. #define STORETYPE U32
  362. #define INNARDS32(f) \
  363.   U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f
  364. #endif
  365.  
  366. static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) {
  367.   INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8));
  368. }
  369.  
  370. static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) {
  371.   INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16));
  372. }
  373.  
  374. static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) {
  375.   INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2]));
  376. }
  377.  
  378. static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) {
  379.   INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24));
  380. }
  381.  
  382. static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) {
  383.   INNARDS32(unsigned(*from) * 0x1010100U);
  384. }
  385.  
  386. static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) {
  387.   INNARDS32(*from * 0x10101U);
  388. }
  389.  
  390. static void
  391. color32_converter(const uchar *from, uchar *to, int w, int delta) {
  392.   INNARDS32(
  393.     (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift));
  394. }
  395.  
  396. static void
  397. mono32_converter(const uchar *from,uchar *to,int w, int delta) {
  398.   INNARDS32(
  399.     (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift));
  400. }
  401.  
  402. ////////////////////////////////////////////////////////////////
  403.  
  404. static void figure_out_visual() {
  405.  
  406.   static XPixmapFormatValues *pfvlist;
  407.   static int FL_NUM_pfv;
  408.   if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv);
  409.   XPixmapFormatValues *pfv;
  410.   for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++)
  411.     if (pfv->depth == fl_visual->depth) break;
  412.   i.format = ZPixmap;
  413.   i.byte_order = ImageByteOrder(fl_display);
  414. //i.bitmap_unit = 8;
  415. //i.bitmap_bit_order = MSBFirst;
  416. //i.bitmap_pad = 8;
  417.   i.depth = fl_visual->depth;
  418.   i.bits_per_pixel = pfv->bits_per_pixel;
  419.  
  420.   if (i.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error
  421.   else bytes_per_pixel = i.bits_per_pixel/8;
  422.  
  423.   unsigned int n = pfv->scanline_pad/8;
  424.   if (pfv->scanline_pad & 7 || (n&(n-1)))
  425.     Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad);
  426.   if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE);
  427.   scanline_add = n-1;
  428.   scanline_mask = -n;
  429.  
  430. #if USE_COLORMAP
  431.   if (bytes_per_pixel == 1) {
  432.     converter = color8_converter;
  433.     mono_converter = mono8_converter;
  434.     return;
  435.   }
  436.   if (!fl_visual->red_mask)
  437.     Fl::fatal("Can't do %d bits_per_pixel colormap",i.bits_per_pixel);
  438. #endif
  439.  
  440.   // otherwise it is a TrueColor visual:
  441.   fl_xpixel(0,0,0); // setup fl_redmask, etc, in fl_color.C
  442.  
  443.   int rs = fl_redshift;
  444.   int gs = fl_greenshift;
  445.   int bs = fl_blueshift;
  446.  
  447.   switch (bytes_per_pixel) {
  448.  
  449.   case 2:
  450.     // All 16-bit TrueColor visuals are supported on any machine with
  451.     // 24 or more bits per integer.
  452. #ifdef U16
  453.     ::i.byte_order = WORDS_BIGENDIAN;
  454. #else
  455.     ::i.byte_order = 1;
  456. #endif
  457.     if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) {
  458.       converter = c565_converter;
  459.       mono_converter = m565_converter;
  460.     } else {
  461.       converter = color16_converter;
  462.       mono_converter = mono16_converter;
  463.     }
  464.     break;
  465.  
  466.   case 3:
  467.     if (::i.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;}
  468.     if (rs == 0 && gs == 8 && bs == 16) {
  469.       converter = rgb_converter;
  470.       mono_converter = rrr_converter;
  471.     } else if (rs == 16 && gs == 8 && bs == 0) {
  472.       converter = bgr_converter;
  473.       mono_converter = rrr_converter;
  474.     } else {
  475.       Fl::fatal("Can't do arbitrary 24bit color");
  476.     }
  477.     break;
  478.  
  479.   case 4:
  480.     if ((::i.byte_order!=0) != WORDS_BIGENDIAN)
  481.       {rs = 24-rs; gs = 24-gs; bs = 24-bs;}
  482.     if (rs == 0 && gs == 8 && bs == 16) {
  483.       converter = xbgr_converter;
  484.       mono_converter = xrrr_converter;
  485.     } else if (rs == 24 && gs == 16 && bs == 8) {
  486.       converter = rgbx_converter;
  487.       mono_converter = rrrx_converter;
  488.     } else if (rs == 8 && gs == 16 && bs == 24) {
  489.       converter = bgrx_converter;
  490.       mono_converter = rrrx_converter;
  491.     } else if (rs == 16 && gs == 8 && bs == 0) {
  492.       converter = xrgb_converter;
  493.       mono_converter = xrrr_converter;
  494.     } else {
  495.       ::i.byte_order = WORDS_BIGENDIAN;
  496.       converter = color32_converter;
  497.       mono_converter = mono32_converter;
  498.     }
  499.     break;
  500.  
  501.   default:
  502.     Fl::fatal("Can't do %d bits_per_pixel",i.bits_per_pixel);
  503.   }
  504.  
  505. }
  506.  
  507. #define MAXBUFFER 0x40000 // 256k
  508.  
  509. static void innards(const uchar *buf, int X, int Y, int W, int H,
  510.             int delta, int linedelta, int mono,
  511.             Fl_Draw_Image_Cb cb, void* userdata)
  512. {
  513.   if (!linedelta) linedelta = W*delta;
  514.  
  515.   int dx, dy, w, h;
  516.   fl_clip_box(X,Y,W,H,dx,dy,w,h);
  517.   if (w<=0 || h<=0) return;
  518.   dx -= X;
  519.   dy -= Y;
  520.  
  521.   if (!bytes_per_pixel) figure_out_visual();
  522.   i.width = w;
  523.   i.height = h;
  524.  
  525.   void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter;
  526.   if (mono) conv = mono_converter;
  527.  
  528.   // See if the data is already in the right format.  Unfortunately
  529.   // some 32-bit x servers (XFree86) care about the unknown 8 bits
  530.   // and they must be zero.  I can't confirm this for user-supplied
  531.   // data, so the 32-bit shortcut is disabled...
  532.   // This can set bytes_per_line negative if image is bottom-to-top
  533.   // I tested it on Linux, but it may fail on other Xlib implementations:
  534.   if (buf && (
  535. #if 0    // set this to 1 to allow 32-bit shortcut
  536.       delta == 4 &&
  537. #if WORDS_BIGENDIAN
  538.       conv == rgbx_converter
  539. #else
  540.       conv == xbgr_converter
  541. #endif
  542.       ||
  543. #endif
  544.       conv == rgb_converter && delta==3
  545.       ) && !(linedelta&scanline_add)) {
  546.     i.data = (char *)(buf+delta*dx+linedelta*dy);
  547.     i.bytes_per_line = linedelta;
  548.  
  549.   } else {
  550.     int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE);
  551.     int blocking = h;
  552.     static STORETYPE *buffer;    // our storage, always word aligned
  553.     static long buffer_size;
  554.     {int size = linesize*h;
  555.     if (size > MAXBUFFER) {
  556.       size = MAXBUFFER;
  557.       blocking = MAXBUFFER/linesize;
  558.     }
  559.     if (size > buffer_size) {
  560.       delete[] buffer;
  561.       buffer_size = size;
  562.       buffer = new STORETYPE[size];
  563.     }}
  564.     i.data = (char *)buffer;
  565.     i.bytes_per_line = linesize*sizeof(STORETYPE);
  566.     if (buf) {
  567.       buf += delta*dx+linedelta*dy;
  568.       for (int j=0; j<h; ) {
  569.     STORETYPE *to = buffer;
  570.     int k;
  571.     for (k = 0; j<h && k<blocking; k++, j++) {
  572.       conv(buf, (uchar*)to, w, delta);
  573.       buf += linedelta;
  574.       to += linesize;
  575.     }
  576.     XPutImage(fl_display,fl_window,fl_gc, &i, 0, 0, X+dx, Y+dy+j-k, w, k);
  577.       }
  578.     } else {
  579. #ifdef __GNUC__
  580.       STORETYPE linebuf[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)];
  581. #else
  582.       STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)];
  583. #endif
  584.       for (int j=0; j<h; ) {
  585.     STORETYPE *to = buffer;
  586.     int k;
  587.     for (k = 0; j<h && k<blocking; k++, j++) {
  588.       cb(userdata, dx, dy+j, w, (uchar*)linebuf);
  589.       conv((uchar*)linebuf, (uchar*)to, w, delta);
  590.       to += linesize;
  591.     }
  592.     XPutImage(fl_display,fl_window,fl_gc, &i, 0, 0, X+dx, Y+dy+j-k, w, k);
  593.       }
  594. #ifndef __GNUC__
  595.       delete[] linebuf;
  596. #endif
  597.     }
  598.   }
  599. }
  600.  
  601. void fl_draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
  602.   innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
  603. }
  604. void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
  605.            int x, int y, int w, int h,int d) {
  606.   innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
  607. }
  608. void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
  609.   innards(buf,x,y,w,h,d,l,1,0,0);
  610. }
  611. void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
  612.            int x, int y, int w, int h,int d) {
  613.   innards(0,x,y,w,h,d,0,1,cb,data);
  614. }
  615.  
  616. void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
  617.   if (fl_visual->depth > 16) {
  618.     fl_color(r,g,b);
  619.     fl_rectf(x,y,w,h);
  620.   } else {
  621.     uchar c[3];
  622.     c[0] = r; c[1] = g; c[2] = b;
  623.     innards(c,x,y,w,h,0,0,0,0,0);
  624.   }
  625. }
  626.  
  627. #endif
  628.  
  629. //
  630. // End of "$Id: fl_draw_image.cxx,v 1.5 1999/01/07 19:17:38 mike Exp $".
  631. //
  632.